#!/usr/bin/env python

'''
	Copyright (C) 2010  Pier Maria Mattioli
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
'''

from clusty import Manager
import traceback
import sys


def help():
	help = """
"help"               : display this help.
"nodes"              : show nodes status.
"rebalance"          : rebalance keys (node recover).
"node \'<node>\'"    : node detail.
"add \'<node>\'"     : add a node.
"del \'<node>\'"     : delete a node.
"redundancy <value>" : change cluster redundancy.
	"""
	return help

def parse_cmd(cmd):
	pard = {}
	pard['action'] = cmd.split()[0]
	node_id = cmd.replace(pard['action'], '', 1).strip()
	if node_id:
		pard['node_id'] = node_id
	return pard

def start_shell(m):
	while True:
		try:
			cmd = raw_input('MGR> ')
			cmd = cmd.strip()
			if cmd in ('bye', 'exit', 'quit'):
				m.shutdown()
				break
			if not cmd:
				continue
			pard = parse_cmd(cmd)
			m._check_container()
			
			if pard['action'] == 'help':
				print help()
				
			elif pard['action'] == 'nodes':
				out = []
				nodes = m.container.keys()
				num_nodes = len(nodes)
				out.append('\n > ---------------------------------------------')
				out.append('-               Active Nodes                -')
				out.append('---------------------------------------------')
				out.append('\n - '.join(nodes)	)
				out.append('---------------------------------------------')
				n_keys = []
				for node_id, node in m.container.items():
					node_keys = m.nodes.do_keys(node, '*')
					n_keys.append([node_id, len(node_keys)])
				tot_keys = sum(k[1] for k in n_keys)
				for k in n_keys:
					k.append((round( (float(k[1]) * 100 / tot_keys), 2)))
					status = ''
					if k[1] == 0:
						status = '.FAILED.'
					out.append(' %s %s %s%% %s' % (k[0].ljust(26),
													 str(k[1]).ljust(8),
													 str(k[2]).ljust(6),
													 status))
				out.append('---------------------------------------------')
				out.append('.............................................')								
				out.append(' Total: %s nodes, %s keys (redundancy = %s)' % (num_nodes, tot_keys, m.redundancy))
				out.append('---------------------------------------------')
				out = '\n > '.join(out)
				print out
			
			elif pard['action'] == 'rebalance':	
				print 'rebalancig', '.' * 10,
				print m.rebalance(pard.get('node_id', None))
			
			elif pard['action'] == 'node':	
				if not 'node_id' in pard:
					print '"node <node_id>"'
					continue
				node = m.nodes.get_node(pard['node_id'])
				result = m.nodes.do_keys(node, '*')
				out = []
				out.append('\n > ---------------------------------------------')
				out.append('-                Node Detail                -')
				out.append('---------------------------------------------')
				out.append('\n > '.join(result))
				out.append('.............................................')								
				out.append(' Total: %s keys for node %s' % (len(result), pard['node_id']))				
				out.append('---------------------------------------------')
				out = '\n '.join(out)				
				print out				
			
			elif pard['action'] == 'add':	
				if not 'node_id' in pard:
					print '"add <node_id>"'
					continue
				print 'adding %(node_id)s' % pard, '.' * 10,
				print m.add_node(pard['node_id'])
			
			elif pard['action'] == 'del':	
				if not 'node_id' in pard:
					print '"del <node_id>"'
					continue
				print 'deleting %(node_id)s' % pard, '.' * 10,
				print m.del_node(pard['node_id'])

			elif pard['action'] == 'redundancy':	
				if not 'node_id' in pard:
					print '"redundancy <value>"'
					continue
				print 'changing %(node_id)s' % pard, '.' * 10,
				print m.change_redundancy(int(pard['node_id']))
			
		except Exception, err:
			type, value, tb = sys.exc_info()
			list = traceback.format_tb(tb, None) + traceback.format_exception_only(type, value)			
			print 'Error:'
			print '\n'.join(list)
	print 'bye'

if __name__ == '__main__':
	if len(sys.argv) < 2:
		sys.exit('usage: python mgr.py <node_id> [<node_id>, ...]')
	nodes = sys.argv[1:]
	m = Manager(nodes=nodes)
	start_shell(m)
